/* ** por compatibilidad se omiten tildes **
================================================================================
 TRABAJO PRACTICO 3 - System Programming - ORGANIZACION DE COMPUTADOR II - FCEN
================================================================================
  definicion de funciones del scheduler
*/
#include "defines.h"
#include "screen.h"
#include "sched.h"
#include "game.h"
#include "i386.h"

#define CANT_JUGADORES 4

unsigned short sched_idle();

unsigned short jugadores_vivos[CANT_JUGADORES];
int cant_jugadores_vivos;
unsigned short tareas[CANT_TAREAS];
unsigned short tarea_actual;
unsigned short jugador_actual_index;
unsigned short gameIniciado = FALSE;

void sched_inicializar() {
    tareas[0] = TAREA_1_GDT_INDEX;
    tareas[1] = TAREA_2_GDT_INDEX;
    tareas[2] = TAREA_3_GDT_INDEX;
    tareas[3] = TAREA_4_GDT_INDEX;
    tareas[4] = TAREA_5_GDT_INDEX;			// arbitro
    tareas[5] = TAREA_IDLE_GDT_INDEX;

    jugadores_vivos[0] = 1; // = {1, 2, 3, 4};
    jugadores_vivos[1] = 2;
    jugadores_vivos[2] = 3;
    jugadores_vivos[3] = 4;
    cant_jugadores_vivos = 4;
    jugador_actual_index = 3;
    
    tarea_actual = 5;
}


unsigned short obtener_proximo_jugador() {
    jugador_actual_index = (jugador_actual_index + 1) % cant_jugadores_vivos;
	return jugadores_vivos[jugador_actual_index];
}

// devuelve el indice de la tarea en la GDT
unsigned short sched_proximo_indice() {
	
    unsigned short result;
    
    if (gameIniciado == FALSE)
    {
		result = tareas[4];
        tarea_actual = 4;
        gameIniciado = TRUE;
        
    } 
    else
    {
		int game_terminado = game_estaTerminado();
		if (game_terminado == TRUE && tarea_actual != 5)
		{
			//return sched_idle();
			tarea_actual = 5;
			result = tareas[5];
		}	// si la tarea actual no es el arbitro, este debe ejecutarse.
		else if (tarea_actual != 4) { 

			result = tareas[4];
			tarea_actual = 4;
		} 	// si la tarea actual es el arbitro, ejecuto algun jugador.
		else {
			unsigned short proxima_tarea = obtener_proximo_jugador() -1;
			result = tareas[proxima_tarea];
			tarea_actual = proxima_tarea;
		}
	}
    return result;
}

void sched_remover_tarea(unsigned int jugador) {
    
    int indice_a_eliminar = -1;
    int idx;
    for (idx=0; idx < cant_jugadores_vivos; ++idx) {
    
        if (jugadores_vivos[idx] == jugador) {
            
            indice_a_eliminar = idx;
        } else {
            if (indice_a_eliminar != -1) {
                jugadores_vivos[indice_a_eliminar] = jugadores_vivos[idx];
                indice_a_eliminar = idx;
            }
        }
    
    }
    cant_jugadores_vivos--;
    
}

unsigned short sched_idle() {
	tarea_actual = 5;
	return tareas[5];
}

unsigned short sched_jugador_actual() {
        return jugadores_vivos[jugador_actual_index];
}

unsigned short sched_indice_actual() {
        return tareas[tarea_actual];
        //return tarea_actual;
}
